﻿/*
 * Copyright 2008 Pimm Hogeling, Karim Sempel and Demian Sempel
 * 
 * This file is part of 8bitplays.
 * 
 * 8bitplays is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 * 
 * 8bitplays is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with 8bitplays. If not, see <http://www.gnu.org/licenses/>.
 */
package nl.sandmen.team.audio {
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.TimerEvent;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.media.SoundTransform;
	import flash.utils.Timer;
	import nl.sandmen.team.data.Track;
	import nl.sandmen.team.events.TrackPlayerEvent;
	import nl.sandmen.team.events.VolumeManagerEvent;
	/**
	 * @author Team Sandmen
	 */
	public class TrackPlayer extends EventDispatcher {
		private var channel:SoundChannel;
		public var preloaded:Boolean;
		private var progressTimer:Timer;
		private var sound:Sound;
		private var stoppedPosition:Number;
		public var track:Track;
		public function TrackPlayer():void {
			progressTimer = new Timer(1000);
			progressTimer.addEventListener(TimerEvent.TIMER, checkTime);
			VolumeManager.addEventListener(VolumeManagerEvent.NEW_VOLUME, newVolume);
		}
		private function checkTime(e:TimerEvent):void {
			dispatchEvent(new TrackPlayerEvent(TrackPlayerEvent.TRACK_PLAYER_PROGRESS, channel.position / (sound.length * sound.bytesTotal / sound.bytesLoaded)));
		}
		private function complete(e:Event):void {
			preloaded = true;
			sound.removeEventListener(IOErrorEvent.IO_ERROR, ioError);
			sound.removeEventListener(Event.COMPLETE, complete);
			dispatchEvent(new TrackPlayerEvent(TrackPlayerEvent.TRACK_PLAYER_PRELOADED));
		}
		private function ioError(e:IOErrorEvent):void {
			sound.removeEventListener(IOErrorEvent.IO_ERROR, ioError);
			sound.removeEventListener(Event.COMPLETE, complete);
			// We try to download the MP3 from a Scene.org HTTP mirror, but if that gives an IOError we'll use the URL supplied
			//  by 8bitpeoples.com.
			preload(track, true);
		}
		private function newVolume(e:VolumeManagerEvent):void {
			if (channel) {
				channel.soundTransform = new SoundTransform(VolumeManager.volume);
			}
		}
		public function play(position:Number = 0):void {
			if (channel) {
				channel.removeEventListener(Event.SOUND_COMPLETE, soundComplete);
			}
			channel = sound.play(position);
			channel.soundTransform = new SoundTransform(VolumeManager.volume);
			channel.addEventListener(Event.SOUND_COMPLETE, soundComplete);
			progressTimer.start();
		}
		public function preload(track:Track, useOriginalRequest:Boolean = false):void {
			this.track = track;
			preloaded = false;
			if (track) {
				if (sound) {
					sound.removeEventListener(IOErrorEvent.IO_ERROR, ioError);
					sound.removeEventListener(Event.COMPLETE, complete);
				}
				sound = new Sound(useOriginalRequest ? track.originalUrlRequest : track.urlRequest);
				if (!useOriginalRequest) {
					sound.addEventListener(IOErrorEvent.IO_ERROR, ioError);
				}
				sound.addEventListener(Event.COMPLETE, complete);
			}
		}
		public function resume():void {
			play(stoppedPosition);
		}
		private function soundComplete(e:Event):void {
			dispatchEvent(new TrackPlayerEvent(TrackPlayerEvent.TRACK_PLAYER_END));
		}
		public function stop():void {
			if (channel) {
				stoppedPosition = channel.position;
				channel.stop();
				channel.removeEventListener(Event.SOUND_COMPLETE, soundComplete);
			}
			progressTimer.stop();
		}
		public function stopPreloading():void {
			if (channel) {
				stop();
				channel = null;
			}
			track = null;
			if (sound) {
				sound.removeEventListener(IOErrorEvent.IO_ERROR, ioError);
				sound.removeEventListener(Event.COMPLETE, complete);
				sound = null;
			}
			preloaded = false;
		}
	}
}